package com.think.cloud.thinkshop.mall.controller.open;

import com.paypal.api.payments.Payment;
import com.stripe.model.Event;
import com.stripe.model.PaymentIntent;
import com.stripe.net.Webhook;
import com.think.cloud.thinkshop.common.enums.ClientEnum;
import com.think.cloud.thinkshop.common.enums.payment.PaymentMethodEnum;
import com.think.cloud.thinkshop.mall.service.payment.PaymentService;
import com.think.cloud.thinkshop.mall.service.payment.paypal.config.PaypalProperties;
import com.think.cloud.thinkshop.mall.service.payment.stripe.config.StripeConfig;
import com.think.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;

/**
 * @author zkthink
 * @apiNote
 **/
@RestController
@Slf4j
@RequestMapping("/callback")
public class PaymentCallbackController {

    @Autowired
    private PaypalProperties paypalProperties;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private StripeConfig stripeConfig;

    @Value("${common.h5-url}")
    private String h5Url;

    @Value("${common.pc-url}")
    private String pcUrl;

    /**
     * PayPal 支付成功 回调
     *
     * @param response
     * @param paymentId
     * @param payerId
     */
    @GetMapping("/paypal/success/{client}")
    public void successPay(@PathVariable("client") String client,HttpServletResponse response, @RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId) {
        log.info("================================payPal 回调成功==================================={}-{}", paymentId, payerId);
        Payment payment = paymentService.executePay(paymentId, payerId);
        try {
            response.sendRedirect(ClientEnum.H5.getCode().equals(client) ? h5Url : pcUrl);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * paypal 回调 取消支付
     *
     * @param response
     * @throws IOException
     */
    @GetMapping("/paypal/cancel/{client}")
    public void cancelPay(@PathVariable("client") String client, HttpServletResponse response) throws IOException {
        log.info("================================payPal 取消支付===================================");
        response.sendRedirect(ClientEnum.H5.getCode().equals(client) ? h5Url : pcUrl);
    }

    @PostMapping("/stripe")
    public void stripeCallback(HttpServletRequest request, HttpServletResponse response) {
        log.info("================================stripe 支付回调===================================");
        try {
            String endpointSecret = stripeConfig.getEndpointSecret();//webhook秘钥签名
            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024 * 4];
            int n = 0;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            String payload = new String(bytes, "UTF-8");
            String sigHeader = request.getHeader("Stripe-Signature");
            Event event = Webhook.constructEvent(payload, sigHeader, endpointSecret);//验签，并获取事件

            log.info("stripeCallback:{}", event);
            PaymentIntent intent = (PaymentIntent)event.getData().getObject();
            if(Objects.isNull(intent)){
                throw new ServiceException("stripeCallback Invalid payload");
            }
//            PaymentIntent intent = (PaymentIntent) event
//                    .getDataObjectDeserializer()
//                    .getObject()
//                    .orElseThrow(() -> new ServiceException("stripeCallback Invalid payload"));

            switch (event.getType()) {
                case "checkout.session.completed"://支付完成
                    break;
                case "checkout.session.expired"://过期
                    break;
                case "payment_intent.created"://创建订单 这里事件就是图二选着的事件
                    break;
                case "payment_intent.canceled"://取消订单
                    break;
                case "payment_intent.succeeded"://支付成功
                    if (intent.getStatus().equals("succeeded")) {
                        log.info("---------------success---------------");
                        String latestCharge = intent.getLatestCharge();
                        String paymentIntentId = intent.getId();
                        Map<String, String> metaData = intent.getMetadata();//自定义传入的参数
                        String orderId = metaData.get("orderId");//自定义订单号
                        log.info("订单号为：{},付款latestCharge:{}", orderId,latestCharge);
                        //*********** 根据订单号从数据库中找到订单，并将状态置为成功 *********//
                        paymentService.paySuccess(orderId,latestCharge,paymentIntentId, PaymentMethodEnum.STRIPE.getCode());
                    }
                    break;
                case "payment_intent.payment_failed"://支付失败
                    log.info("Failed: " + intent.getId());
                    log.info("---------------payment_failed---------------");
                    Map<String, String> metaData = intent.getMetadata();//自定义传入的参数
                    String orderId = metaData.get("orderId");//自定义订单号
                    log.info("订单号为：{}", orderId);
                    paymentService.payFailed(orderId);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("stripe异步通知（webhook事件）", e);
        }
    }
}
